﻿using MatrixEditor.Properties;
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Text;
using System.Windows.Forms;
using static MatrixEditor.Global;

namespace MatrixEditor
{
	public partial class FrmData : Form
	{
		private const string DEFAULT_PERIOD = "100"; // ms
		private const string DEFAULT_NAME   = "NONAME"; // ms

		private readonly string code_name_prefix   = "名称：";
		private readonly string code_period_prefix = "间隔：";

		private string code_name   = DEFAULT_NAME;
		private string code_period = DEFAULT_PERIOD;
		private bool code_loops    = true;
		private bool code_comments = true;
		private bool code_show_hex = true;

		private bool mode_single_color = true;
		private bool mode_import_data  = false;

		public FrmData() => InitializeComponent();

		#region 自定义函数
		public void GeneratePythonCode()
		{
			if (!Visible) { return; }

			var code = new StringBuilder();
			string suffix;
			bool new_line;

			if (!mode_single_color)
			{
				code.AppendLine($"COLOR_PALETTE = (");

				for (int index = 0; index < Colors.GetLength(0); index++)
				{
					if ((index + 1) % 4 == 0)
					{
						suffix = "";
						new_line = true;
					}
					else
					{
						suffix = " ";
						new_line = false;
					}

					if (index % 4 == 0) { code.Append($"\t"); }

					if (code_show_hex)
					{
						code.Append($"(0x{Colors[index, 0]:x2}, 0x{Colors[index, 1]:x2}, 0x{Colors[index, 2]:x2}),{suffix}");
					}
					else
					{
						code.Append($"({Colors[index, 0]}, {Colors[index, 1]}, {Colors[index, 2]}),{suffix}");
					}

					if (new_line) { code.AppendLine(); }
				}

				code.AppendLine($")").AppendLine();
			}

			code.AppendLine($"{code_name}: {{");
			code.AppendLine($"\t'period': {code_period},");
			
			// default: true
			if (!code_loops) { code.AppendLine($"\t'loops' : {code_loops},"); }
			if (!mode_single_color) { code.AppendLine($"\t'color' : {!mode_single_color},"); }

			code.AppendLine("\t'frames': {");

			for (int index = 0; index < Frames.Count; index++)
			{
				var comment     = new StringBuilder();
				var color_data  = new StringBuilder();
				string temp     = string.Empty;

#if false

				int color_index = 0;

				foreach (int pixel in Frames[index])
				{
					comment.Append($"{(pixel == 0 ? "0" : "1")}");

					if (code_show_hex)
					{
						temp += pixel.ToString("d2");
						suffix = color_index == Frames[index].Length - 1 ? "," : ", ";

						if ((color_index + 1) % 6 == 0)
						{
							color_data.Append($"0x{string.Format("{0:x10}", Convert.ToUInt64(temp))}{suffix}");
							temp = "";
						}
					}
					else
					{
						suffix = color_index == Frames[index].Length - 1 ? "," : ", ";
						color_data.Append($"{pixel}{suffix}");
					}

					color_index++;
				}

#else

				using (MemoryStream memory_stream = new MemoryStream())
				{
					using (DeflateStream deflate_stream = new DeflateStream(memory_stream, CompressionMode.Compress, true))
					{
						foreach (int pixel in Frames[index])
						{
							comment.Append($"{(pixel == 0 ? "0" : "1")}");

							if (code_show_hex)
							{
								deflate_stream.WriteByte(Convert.ToByte(pixel));
							}
						}
					}

					color_data.Append(string.Join(", ", memory_stream.ToArray()));
				}

#endif

				if (mode_single_color)
				{
					code.Append($"\t\t{index,2}: 0x{Convert.ToUInt64(comment.ToString(), 2):x14},");
					code.AppendLine(code_comments ? $" # {comment}" : "");
				}
				else
				{
					code.Append($"\t\t{index,2}: ({color_data}),");
					code.AppendLine(code_comments ? $" # {comment}" : "");
				}
			}

			code.AppendLine("\t},");
			code.AppendLine("},");

			TextBoxDataCode.Text = code.ToString();

			RefreshStatusBar();
		}

		private void ImportDataFromClipBoard()
		{
			var frames_string = new List<string>(20);

			using (var reader = new StringReader(Clipboard.GetText(TextDataFormat.Text)))
			{
				int index;
				string line = reader.ReadLine();

				while (line != null)
				{
					line = line.Trim().Trim('\t');
					index = line.IndexOf("0x", StringComparison.CurrentCultureIgnoreCase);

					if (index > 0)
					{
						line = line.Substring(index);
						index = line.IndexOf(",");

						if (index > 0) { line = line.Substring(0, index); }
						else
						{
							index = line.IndexOf(" ");

							if (index > 0) { line = line.Substring(0, index); }
						}

						try
						{
							Convert.ToInt64(line, 16);
							frames_string.Add(line);
						}
						catch (FormatException) { }
					}

					line = reader.ReadLine();
				}
			}

			if (frames_string.Count > 0)
			{
				(Owner as FrmMain).RemoteLoadThumbnail(frames_string);
				GeneratePythonCode();
			}

			RefreshStatusBar();
			mode_import_data = false;
		}

		/// <summary>
		/// 在状态栏显示文本框相关信息
		/// </summary>
		private void RefreshStatusBar()
		{
			int index  = TextBoxDataCode.GetFirstCharIndexOfCurrentLine();
			int line   = TextBoxDataCode.GetLineFromCharIndex(index) + 1;
			int column = TextBoxDataCode.SelectionStart - index;
			int bytes  = Encoding.UTF8.GetByteCount(TextBoxDataCode.Text);

			StatusLabelPosition.Text   = $"行：{line}，列：{column}";
			StatusLabelBytesCount.Text = $"{bytes} 字节";
		}
		#endregion


		#region 窗体控件事件
		private void TextBoxDataCode_KeyUp(object sender, KeyEventArgs e) => RefreshStatusBar();

		private void TextBoxDataCode_MouseUp(object sender, MouseEventArgs e) => RefreshStatusBar();

		private void FrmData_Load(object sender, EventArgs e)
		{
			TextBoxDataCode.Text          = string.Empty;
			TextBoxDataCode.SelectionTabs = new int[] { 32, 64, 96, 128 };

			code_loops        = Settings.Default.DataLoops;
			code_comments     = Settings.Default.DataComments;
			code_show_hex     = Settings.Default.DataShowHex;
			mode_single_color = Settings.Default.DataSingleColor;

			ComboBoxMode.SelectedIndex = mode_single_color ? 0 : 1;

			RefreshStatusBar();
		}

		private void FrmData_FormClosing(object sender, FormClosingEventArgs e)
		{
			if (e.CloseReason == CloseReason.UserClosing)
			{
				Visible = false;
				e.Cancel = true;

				(Owner as FrmMain).CheckMainFormStatus();
			}
		}

		private void FrmData_VisibleChanged(object sender, EventArgs e)
		{
			if (Visible) { GeneratePythonCode(); }

			(Owner as FrmMain).CheckMainFormStatus();
		}
		#endregion


		#region 菜单控件事件
		private void MenuItemHide_Click(object sender, EventArgs e)
		{
			(Owner as FrmMain).MenuItemViewData_Click(sender, e);
		}

		private void MenuItemPlayer_Click(object sender, EventArgs e)
		{
			var frmMain = Owner as FrmMain;

			(frmMain.PlayerForm.Visible ?
				new Action(
					() => frmMain.PlayerForm.BringToFront()
				) :
				() => frmMain.MenuItemViewPlayer_Click(sender, e)
			)();
		}

		private void MenuStripTextBox_Opened(object sender, EventArgs e)
		{
			TextBoxName.Text   = $"{code_name_prefix}{code_name}";
			TextBoxPeroid.Text = $"{code_period_prefix}{code_period}";

			MenuItemLoops.Checked    = code_loops;
			MenuItemComments.Checked = code_comments;
			MenuItemShowHex.Checked  = code_show_hex;

			ComboBoxMode.SelectedIndex = mode_single_color ? 0 : 1;
		}

		private void MenuStripTextBox_Closed(object sender, ToolStripDropDownClosedEventArgs e)
		{
			code_name         = TextBoxName.Text.Trim(code_name_prefix.ToCharArray()) ?? DEFAULT_NAME;
			code_period       = TextBoxPeroid.Text.Trim(code_period_prefix.ToCharArray()) ?? DEFAULT_PERIOD;
			code_loops        = MenuItemLoops.Checked;
			code_comments     = MenuItemComments.Checked;
			code_show_hex     = MenuItemShowHex.Checked;
			mode_single_color = ComboBoxMode.SelectedIndex == 0;

			(mode_import_data ? new Action(() => ImportDataFromClipBoard()) : () => GeneratePythonCode())();
		}

		private void TextBoxName_Click(object sender, EventArgs e)
		{
			TextBoxName.Text = code_name;
			TextBoxName.SelectAll();
		}

		private void TextBoxName_KeyPress(object sender, KeyPressEventArgs e)
		{
			if (e.KeyChar == (char)13) { MenuStripTextBox.Close(); }
		}

		private void TextBoxPeroid_Click(object sender, EventArgs e)
		{
			TextBoxPeroid.Text = code_period;
			TextBoxPeroid.SelectAll();
		}

		private void TextBoxPeroid_KeyPress(object sender, KeyPressEventArgs e)
		{
			if (!char.IsNumber(e.KeyChar) && !char.IsControl(e.KeyChar))
			{
				e.Handled = true;
			}

			if (e.KeyChar == (char)13) { MenuStripTextBox.Close(); }
		}

		private void ComboBoxMode_SelectedIndexChanged(object sender, EventArgs e)
		{
			mode_single_color = ComboBoxMode.SelectedIndex == 0;

			Settings.Default.DataSingleColor = mode_single_color;
			Settings.Default.Save();

			GeneratePythonCode();

			MenuStripTextBox.Close();
		}

		private void MenuItemLoops_MouseDown(object sender, MouseEventArgs e)
		{
			code_loops = MenuItemLoops.Checked = !MenuItemLoops.Checked;

			Settings.Default.DataLoops = code_loops;
			Settings.Default.Save();
		}

		private void MenuItemComments_MouseDown(object sender, MouseEventArgs e)
		{
			code_comments = MenuItemComments.Checked = !MenuItemComments.Checked;

			Settings.Default.DataComments = code_comments;
			Settings.Default.Save();
		}

		private void MenuItemShowHex_MouseDown(object sender, MouseEventArgs e)
		{
			code_show_hex = MenuItemShowHex.Checked = !MenuItemShowHex.Checked;

			Settings.Default.DataShowHex = code_show_hex;
			Settings.Default.Save();
		}

		private void MenuItemRefresh_Click(object sender, EventArgs e) => GeneratePythonCode();

		private void MenuItemCopy_Click(object sender, EventArgs e)
		{
			Clipboard.SetText(TextBoxDataCode.Text);
		}

		private void MenuItemImportData_MouseDown(object sender, MouseEventArgs e)
		{
			mode_import_data = true;
		}
		#endregion
	}
}
